﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Version2;
using System.Collections.Generic;
using LinqToTwitter;
using System.Linq;
using System.Threading;

namespace SocialMedia4LETests
{
    [TestClass]
    public class TwitterizerTests
    {
        [TestMethod]
        public void StreamFromUsersTwitter()
        {
            var auth = new SingleUserAuthorizer
            {
                Credentials = new InMemoryCredentials
                {
                    ConsumerKey = @"TFFBLnE35TrHILtrH8wQtQ",
                    ConsumerSecret = @"cU925O6BSTsB9r1M0oTelra2DXrPPAZlTg9V3EieLjE",
                    AccessToken = @"ke2wP0XDBtG1YJFMt5aw44OKfkYegzBRhmEtPBn4",
                    OAuthToken = @"872808954-qdGXOUlGI6KlERDy9d8hLApUl7jG515a0SB88Xmp"
                }
            };

            TwitterContext twitterCtx = new TwitterContext(auth);
            string ids = "";

            Friendship friendship;
            string cursor = "-1";
            do
            {
                friendship =
                    (from friend in twitterCtx.Friendship
                     where friend.Type == FriendshipType.FriendsList &&
                           friend.ScreenName == "KingNebby" &&
                           friend.Cursor == cursor
                     select friend)
                    .SingleOrDefault();

                cursor = friendship.CursorMovement.Next;

                friendship.Users.ForEach(friend =>
                {
                    if (friend.Identifier.ScreenName.StartsWith("Seattle"))
                    {
                        ids += friend.Identifier.UserID + ",";
                    }
                });

            } while (cursor != "0");
            ids = ids.Substring(0, ids.Length - 1);
            Console.WriteLine("All ids: \n{0}\n", ids);

            int count = 0;
            UserStream str = (from stream in twitterCtx.UserStream
             where stream.Type == UserStreamType.User
             && stream.Follow == ids
             select stream)
                    .StreamingCallback(stream =>
                    {
                        if (stream.Content.Length > 0)
                        {
                            Console.WriteLine(stream.Content + "\n");
                            if (count++ >= 2)
                            {
                                stream.CloseStream();
                            }
                        }
                    }).SingleOrDefault();
            while (count < 2)
            {
                Thread.Sleep(1000);
            }
            str.CloseStream();
        }
        [TestMethod]
        public void TestCoordinates()
        {
            double invalid_lat = -939;
            double invalid_lon = 939;
            double valid_lat = 0;
            double valid_lon = 0;
            TwitterUtil tUt = new TwitterUtil();
            bool ret = tUt.CheckCoordinates(invalid_lat, valid_lon);
            Assert.IsFalse(ret, "The lat should be invalid.");
            ret = tUt.CheckCoordinates(valid_lat, invalid_lon);
            Assert.IsFalse(ret, "The lon should be invalid.");
            ret = tUt.CheckCoordinates(invalid_lat, invalid_lon);
            Assert.IsFalse(ret, "The lat and lon should be invalid.");
            ret = tUt.CheckCoordinates(valid_lat, valid_lon);
            Assert.IsTrue(ret, "The lat and lon should be valid.");
        }

        [TestMethod]
        public void TestLinq2Twit()
        {
            var auth = new SingleUserAuthorizer
            {
                Credentials = new InMemoryCredentials
                {
                    ConsumerKey = @"TFFBLnE35TrHILtrH8wQtQ",
                    ConsumerSecret = @"cU925O6BSTsB9r1M0oTelra2DXrPPAZlTg9V3EieLjE",
                    AccessToken = @"ke2wP0XDBtG1YJFMt5aw44OKfkYegzBRhmEtPBn4",
                    OAuthToken = @"872808954-qdGXOUlGI6KlERDy9d8hLApUl7jG515a0SB88Xmp"
                }
            };

            TwitterContext cntx = new TwitterContext(auth);
            var srch =
                   (from search in cntx.Search
                    where search.Type == SearchType.Search &&
                          search.Query == " " &&
                          search.Count == 10 &&
                          search.GeoCode == @"47.619920,-122.348725,5mi"
                    // If I add this it's going to look at yesterday, simply leave off to start from today.
                    //search.Until == DateTime.Now.Date
                    select search)
                   .SingleOrDefault();

            if (srch == null || srch.SearchMetaData == null)
            {
                Console.WriteLine("Found no results based on string");
                return;
            }

            Console.WriteLine("\nQuery: {0}\n", srch.SearchMetaData.Query);
            srch.Statuses.ForEach(entry =>
                Console.WriteLine(
                    "ID: {0, -15}, Source: {1}\nContent: {2}\n Time: {3}\nGeoLoc: {4}",
                    entry.StatusID, entry.Source, entry.Text, entry.CreatedAt,
                    String.Format("({0},{1})", entry.Coordinates.Latitude, entry.Coordinates.Longitude)));
        }

        [TestMethod]
        public void TestPaging()
        {
            TwitterUtil util = new TwitterUtil();
            // This should only bring tweets 10 min in the past.
            List<SocialDataPoint> data = util.getTweets(47.619920, -122.348725, 1,
                DateTime.Now, 5, new TwitterUtil.SocialMedium[] { TwitterUtil.SocialMedium.TWITTER });
            Assert.IsNotNull(data, "Data should not be null!");
            Console.WriteLine("Total points found: {0}", data.Count);
            Console.WriteLine("Local time:{0}, GMT:{1}", DateTime.Now, DateTime.Now.ToUniversalTime());
            foreach (var p in data)
            {
                Console.WriteLine("{0}", p.BirthDate);
            }
        }

        [TestMethod]
        public void OptimizedSearching()
        {
            TwitterSearchMetadata md = new TwitterSearchMetadata();
            DateTime current = DateTime.Now.AddMinutes(-10);
            // Searching from -5 min to -15 mins.
            SearchParameters sp = new SearchParameters()
            {
                Radius = 1.0,
                Address = "addr",
                MinutesBeforeAndAfter = 5,
                Latitude = 1.0,
                Longitude = 1.0,
                ID = 0,
                DateAndTime = current
            };

            Assert.IsFalse(md.canReturnSameData(sp));

            // Assume search succeeded with these results.
            SocialDataPoint old = new SocialDataPoint() { BirthDate = current.AddMinutes(-10), Id = 10 };
            SocialDataPoint recent = new SocialDataPoint() { BirthDate = DateTime.Now, Id = 20 };

            // If we just udpated, should just return.
            md.updateLastSearchMetadata(sp, old, recent);
            Assert.IsTrue(md.canReturnSameData(sp));

            // if we change radius, address, or lat lon, need new search.
            sp.Address = "addr1";
            Assert.IsFalse(md.canReturnSameData(sp));

            md.updateLastSearchMetadata(sp, old, recent);
            sp.Radius = 1.0001;
            Assert.IsFalse(md.canReturnSameData(sp));

            md.updateLastSearchMetadata(sp, old, recent);
            sp.Latitude = 2.0;
            Assert.IsFalse(md.canReturnSameData(sp));

            md.updateLastSearchMetadata(sp, old, recent);
            sp.Longitude = 2.0;
            Assert.IsFalse(md.canReturnSameData(sp));

            // Input basic search.
            sp = new SearchParameters()
            {
                Radius = 1.0,
                Address = "addr",
                MinutesBeforeAndAfter = 5,
                Latitude = 1.0,
                Longitude = 1.0,
                ID = 0,
                DateAndTime = current
            };
            md.updateLastSearchMetadata(sp, old, recent);

            // Now, increase window beyond the -5, -15 window and see that we get id's matching our high/lows
        }
    }
}
